#include <bcm/bcm.h>
#include <iostream>

struct {
	LPCTSTR dllName;
	const char *id;
} component[] = {
	{ TEXT("rte.dll"), "rte" },
	{ TEXT("millkernel.dll"), "millkrnl" },
	{ TEXT("milldatabase.dll"), "milldb" },
	{ TEXT("executive.dll"), "exec" },
	{ TEXT("millmemory.dll"), "millmem" },
	{ TEXT("codecmgr.dll"), "codecmgr" },
	{ TEXT("portmgr.dll"), "portmgr" },
	{ TEXT("uimgr.dll"), "uimgr" },
	{ TEXT("uikeyboard.dll"), "uikbd" },
	{ TEXT("gcodecompiler.dll"), "gcode" },
	{ TEXT("progdb.dll"), "progdb" },
	{ TEXT("motion.dll"), "mc" },
	{ TEXT("plc.dll"), "lc" },
	{ 0, 0 }
};

bool displayComponent(LPCTSTR dllName, const char *id)
{
	bcm::ComponentManager &compMgr = bcm::ComponentManager::instance();
	switch (compMgr.loadComponent(dllName)) {
	case bcm::LC_NODLL:
		std::cout << "Could not load DLL " << id << "." << std::endl;
		break;
	case bcm::LC_NOCOMPONENT:
		std::cout << "Could not read component " << id << "." << std::endl;
		break;
	case bcm::LC_ALREADYUSED:
		std::cout << "Component " << id << " already registered." << std::endl;
		break;
	case bcm::LC_OK:
		std::cout << "Component " << id << " load OK." << std::endl;
		break;
	}
	bcm::Component *component;
	switch (compMgr.getComponent(id, &component)) {
	case bcm::GC_UNREGISTERED:
		std::cout << "Component " << id << " never registered.\n" << std::endl;
		return false;
	case bcm::GC_NOCOMPONENT:
		std::cout << "Component " << id << " unavailable.\n" << std::endl;
		return false;
	case bcm::GC_INCOMPLETE:
		std::cout << "Component " << id << " load incomplete.\n" << std::endl;
		return false;
	case bcm::GC_OK:
		std::cout << "Component " << id << " retrieval OK." << std::endl;
		break;
	}
	bcm::IdentifierData *ifaces;
	int i;
	ifaces = component->getProvidedInterfaceTable();
	std::cout << "Interfaces provided by " << id << ":" << std::endl;
	for (i = 0; ifaces[i].id != 0; i++)
		std::cout << '\t' << ifaces[i].id << " = " << ifaces[i].name << std::endl;
	if (i == 0)
		std::cout << "\tNone" << std::endl;
	ifaces = component->getRequiredInterfaceTable();
	std::cout << "Interfaces required by " << id << ":" << std::endl;
	for (i = 0; ifaces[i].id != 0; i++)
		std::cout << '\t' << ifaces[i].id << " = " << ifaces[i].name << std::endl;
	if (i == 0)
		std::cout << "\tNone" << std::endl;
	std::cout << std::endl;
	return true;
}

struct {
	const char *idServer;
	const char *idClient;
	const char *idIface;
} assignment[] = {
	{"rte", "uimgr", "enventities" },
	{"milldb", "millmem", "millpdata" },
	{"milldb", "uimgr", "millpdata" },
	{"exec", "millkrnl", "machop" },
	{"millmem", "exec", "gdata" },
	{"millmem", "uimgr", "gdata" },
	{"millmem", "mc", "gdata" },
	{"millmem", "lc", "gdata" },
	{"codecmgr", "millkrnl", "kbd" },
	{"portmgr", "codecmgr", "dataport" },
	{"uimgr", "millkrnl", "uiservs" },
	{"uikbd", "codecmgr", "vkbd" },
	{"gcode", "exec", "cmdstream" },
	{"progdb", "gcode", "progmgr" },
	{"progdb", "uimgr", "progmgr" },
	{"mc", "exec", "motctl" },
	{"lc", "exec", "logicctl" },
	{ 0, 0, 0 }
};

bool linkComponents(const char *idServer, const char *idClient, const char *idIface)
{
	bcm::ComponentManager &compMgr = bcm::ComponentManager::instance();
	bcm::Component *server;
	switch (compMgr.getComponent(idServer, &server)) {
	case bcm::GC_UNREGISTERED:
		std::cout << "Server " << idServer << " never registered.\n" << std::endl;
		return false;
	case bcm::GC_NOCOMPONENT:
		std::cout << "Server " << idServer << " unavailable.\n" << std::endl;
		return false;
	case bcm::GC_INCOMPLETE:
		std::cout << "Server " << idServer << " load incomplete.\n" << std::endl;
		return false;
	case bcm::GC_OK:
		std::cout << "Server " << idServer << " retrieval OK." << std::endl;
		break;
	}
	bcm::Component *client;
	switch (compMgr.getComponent(idClient, &client)) {
	case bcm::GC_UNREGISTERED:
		std::cout << "Client " << idClient << " never registered.\n" << std::endl;
		return false;
	case bcm::GC_NOCOMPONENT:
		std::cout << "Client " << idClient << " unavailable.\n" << std::endl;
		return false;
	case bcm::GC_INCOMPLETE:
		std::cout << "Client " << idClient << " load incomplete.\n" << std::endl;
		return false;
	case bcm::GC_OK:
		std::cout << "Client " << idClient << " retrieval OK." << std::endl;
		break;
	}
	bcm::Interface *iface = server->getInterface(idIface);
	if (iface == 0) {
		std::cout << "Could not get interface " << idIface << " from server "
			<< idServer << " (for client " << idClient << ")." << std::endl;
		return false;
	}
	if (client->setInterface(server->getInterface(idIface)) == false) {
		std::cout << "Could not assign interface " << idIface << " from server "
		<< idServer << " to client " << idClient << "." << std::endl;
		return false;
	}
	std::cout << "Interface " << idIface << " from server "
		<< idServer << " assigned to client " << idClient << "." << std::endl;
	return true;
}

int main()
{
	for (int i = 0; component[i].dllName != 0; i++)
		displayComponent(component[i].dllName, component[i].id);
	for (int i = 0; assignment[i].idIface != 0; i++)
		linkComponents(assignment[i].idServer, assignment[i].idClient, assignment[i].idIface);
	return 0;
}

